Using Django on Smeserver 7.5
Introduction
Creating web-based information systems with Django is fun. For deployment of the productive system I wanted to use an Smeserver 7.5. SME7 is based on CentOS 4.X, which comes with Python 2.3.4. This restricts you to Django 1.1 together with Python 2.3, which are — to put it mildly — outdated. At the time of this writing Django 1.4 with Python 2.7 is a charme. Thus, I figured out how to put Django 1.4 at Python 2.7 onto an SME 7.5. Please let me know if you spot any errors or omissions. Here we go…
Problem Statement
We assume a working installation of Smeserver 7.5 as myserver. Further, we assume a working django project using Python 2.7 on any development host. We declare the metasyntactic variable myDjangoProject as the django project’s name. We declare the metasyntactic variable xyz as myserver’s path (i.e.,
http(s)://myserver/xyz) where the django project should be provided. The server should host and provide the django project.
The Method
First, we create an isolated environment for our installation. Go to the server admin page and create an user django. For security reasons we won’t give the django user any super user rights. Therefore, login as user django on one terminal and login as user root on another terminal. Assume user django’s context first throughout the instructions if not stated otherwise.
Inside user root’s context install required development packages. We will remove them when we are done, because they are an attack vector.
yum install gcc
export PYTHONPATH=$PYTHONPATH:$HOME/code/python
mkdir -p code/python
export SOURCEDIR=$HOME/source
mkdir $SOURCEDIR
export LOCALDIR=$HOME/local
mkdir $LOCALDIR
export PATH=$LOCALDIR/bin:$PATH
touch .bashrc
ln .bashrc .bash_profile
nano .bashrc
In the .bashrc file append the following lines:export PYTHONPATH=$PYTHONPATH:$HOME/code/python
export LOCALDIR=$HOME/local
export PATH=$LOCALDIR/bin:$PATH
Exit from nano with Ctrl+X and say “Yes, I want to save the .bashrc file.” Then proceed in user django’s shell:
cd $SOURCEDIR
wget http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tar.bz2
tar -xjf Python-2.7.3.tar.bz2
cd Python-2.7.3
./configure --prefix=$LOCALDIR
make
make install
Test your Python! It should look something like this:
-bash-3.00$ python
Python 2.7.3 (default, Apr 12 2012, 18:57:10)
[GCC 3.4.6 20060404 (Red Hat 3.4.6-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
We want to use PIP in user django’s context.
cd $SOURCEDIR
wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg
sh setuptools-0.6c11-py2.7.egg --prefix=$LOCALDIR
easy_install PIP
pip install django
It’s time to setup the django site. If you want to build one from scratch refer to
Django's great tutorial. I take mine from my development repository. No matter how, put your django project into user django’s code directory (i.e., ~/code/python), which we refer to in the pythonpath environment variable.
cd ~/code/python
svn co https://mySvnServer.tld/myRepository/myDjangoProject myDjangoProject
For the fun of it, let’s peek test our django installation.
cd myDjangoProject
python manage.py syncdb
python manage.py runserver
I guess it complains about missing packages. Use PIP to fix this. Because additional packages are quiet individual I think you should go on your own here. I collected some experiences down in the section called
Optional Packages↓. Repeat the test until the test server succeeds. Then, we stop the test server and set it up for productive service with fastcgi following the instructions from
http://wiki.contribs.org/Mod_FastCGI inside user root’s context.
cd ~
wget http://mirror.contribs.org/smeserver/contribs/nhall/sme7/contribs/mod_fastcgi/rpms/mod_fastcgi-2.4.6-1.i386.rpm
wget http://mirror.contribs.org/smeserver/contribs/nhall/sme7/contribs/mod_fastcgi/rpms/smeserver-mod_fastcgi-0.1-1.noarch.rpm
yum localinstall smeserver-mod_fastcgi-0.1-1.noarch.rpm mod_fastcgi-2.4.6-1.i386.rpm
Django’s fast_cgi server requires the python flup package.
pip install flup
python manage.py runfcgi daemonize=false method=threaded host=127.0.0.1 port=3533
We adapt their instructions how to configure the Apache to smeserver’s configuration template system. Configure Django’s fcgi server as Apache’s external fcgi server.
mkdir -p /etc/e-smith/templates-custom/etc/httpd/conf/httpd.conf
nano /etc/e-smith/templates-custom/etc/httpd/conf/httpd.conf/80FastCgiExternalServer
FastCgiExternalServer external_django_fastcgi_server -host 127.0.0.1:3533
Then we configure, how Apache should route requests to the fcgi server. For this, we assume that you want to publish your django project at
http(s)://yourserver/xyz root url.
mkdir /etc/e-smith/templates-custom/etc/httpd/conf/httpd.conf/VirtualHosts
nano /etc/e-smith/templates-custom/etc/httpd/conf/httpd.conf/VirtualHosts/69django
Alias /xyz external_django_fastcgi_server
<Location /xyz >
SetHandler fastcgi-script
Options +ExecCGI
allow from all
</Location>
Then we apply the two new templates through:
expand-template /etc/httpd/conf/httpd.conf
sv t httpd-e-smith
Now, your django project should be accessible under
http(s)://yourserver/xyz. The last issue is, that we manually started the fcgi server. First, stop the manually started server (Ctrl+C). Then as user django create an executable runserver script.
touch ~/runserver
chmod u+x ~/runserver
nano ~/runserver
#!/bin/sh
cd ~/code/python/myDjangoProject
python manage.py runfcgi daemonize=false method=threaded host=127.0.0.1 port=3533
Then, we link the runserver script into smeserver’s startup framework.
db configuration set django service status enabled
ln -s /etc/rc.d/init.d/e-smith-service /etc/rc.d/rc7.d/S85django
ln -s /etc/rc.d/init.d/daemontools /etc/rc.d/init.d/django
mkdir /var/service/django
ln -s /var/service/django /service/django
touch /var/service/django/run
chmod u+x /var/service/django/run
nano /var/service/django/run
#!/bin/sh
su -l --command=~/runserver django
Now, your django project should be available 24/7. That’s it.
Polishing for Security
Remove all development packages! They are an attack vector.
yum remove gcc cpp *-devel *headers
Set as much files as possible to read-only. Finally, your sqlite database file should be the only writable file inside django’s home when going online.
Optional Packages
south
Never again without south! I developed with south 0.7.3. When I deployed, pip retrieved south 0.7.4, which produced syntax errors at SQL. I pinned south to version 0.7.3 and it was fixed.
pip install south==0.7.3
django-simple-captcha
I use django-simple-captcha. This is not trivial, because it uses _imagingft through the PIL, which doesn’t install properly out-of-the-box. Here’s how I did it.
yum install gcc freetype-devel
pip install PIL
yum remove gcc freetype-devel
pip install django-simple-captcha
smtplib.SMTP_SSL
As you have Django running on your smeserver you want to send emails with the very same server, of course. This requires an ssl-enabled smtp client. If python complains about a missing
SMTP_SSL class then the
_ssl module is missing. You need to have the
openssl-devel package yum-installed during the python build to fix this. If you forgot it at first just rebuild python with an available
openssl-devel package following the configure-make-makeinstall-instructions stated at the top of the section called
The Method↑. Please don’t forget to remove any devel packages afterwards!
pysqlite
If you configured the sqlite backend, django complains about missing pysqlite package out-of-the-box. Here’s how I did it.
yum install gcc sqlite-devel
pip install pysqlite
yum remove gcc sqlite-devel